package com.bot.nft.module.dc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bot.common.exception.CommonException;
import com.bot.dev.api.DevBlockChainApi;
import com.bot.nft.core.enums.dc.NftInfoEnum;
import com.bot.nft.core.util.NftCodeUtil;
import com.bot.nft.module.chain.mapper.ChainOptLogMapper;
import com.bot.nft.module.dc.domain.DcNftDict;
import com.bot.nft.module.dc.domain.DcNftInfo;
import com.bot.nft.module.dc.domain.bo.DcNftInfoBo;
import com.bot.nft.module.dc.domain.vo.DcAuthorInfoVo;
import com.bot.nft.module.dc.domain.vo.DcNftDictVo;
import com.bot.nft.module.dc.domain.vo.DcNftInfoVo;
import com.bot.nft.module.dc.domain.vo.NftDictVo;
import com.bot.nft.module.dc.mapper.DcAuthorInfoMapper;
import com.bot.nft.module.dc.mapper.DcNftDictMapper;
import com.bot.nft.module.dc.mapper.DcNftInfoMapper;
import com.bot.nft.module.dc.service.IDcNftInfoService;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author RenXiaoZheng
 * @since 2024-01-24
 */
@Service
public class DcNftInfoServiceImpl extends ServiceImpl<DcNftInfoMapper, DcNftInfo> implements IDcNftInfoService {

    @Resource
    private DcNftInfoMapper dcNftMapper;

    @Resource
    private DcNftDictMapper dcNftDictMapper;

    @Resource
    private DcAuthorInfoMapper dcAuthorInfoMapper;

    @Resource
    private DcNftDictMapper nftDictMapper;

    @Resource
    private DevBlockChainApi devBlockChainApi;

    @Resource
    public ChainOptLogMapper chainOptLogMapper;


    /**
     * 添加藏品信息
     *
     * @param dcNftInfoBo 藏品信息，包含藏品名称、藏品价格、藏品描述等属性
     * @return
     */
    @Override
    public Boolean addDcNftInfo(DcNftInfoBo dcNftInfoBo) {

        //藏品价格比对
        if (dcNftInfoBo.getPrice() != null) {
            int result = dcNftInfoBo.getHighPrice().compareTo(dcNftInfoBo.getLowPrice());
            if (result < 0) throw new CommonException("最高发售价格不得小于最低发售价格");
        }
        //entity转Bo
        DcNftInfo dcNftInfo = BeanUtil.copyProperties(dcNftInfoBo, DcNftInfo.class);
        DateTime dateTime = new DateTime();
        dcNftInfo.setCreateTime(dateTime);
        //获取创作者信息
        DcAuthorInfoVo authorDcInfoBo = dcNftInfoBo.getAuthorDcInfoBo();
        dcNftInfo.setInventory(dcNftInfoBo.getPublishNum());
        //藏品Id
        //dcNftInfo.setId(IdUtil.getSnowflakeNextIdStr());
        //获取创作者id标识
        dcNftInfo.setAuthorId(authorDcInfoBo.getId());
        dcNftInfo.setNftShow(NftInfoEnum.NFT_SHOW.getValue());
        dcNftInfo.setType(NftInfoEnum.NFT_TYPE.getValue());
        dcNftInfo.setContract(String.valueOf(UUID.randomUUID()));
        int insert = dcNftMapper.insert(dcNftInfo);
        //取出字典信息
        List<String> plates = dcNftInfoBo.getPlates();
        List<DcNftDict> dcNftDicts = new ArrayList<>();
        for (String plate : plates) {
            DcNftDict dcNftDict = new DcNftDict();
            dcNftDict.setNftId(dcNftInfo.getId());
            dcNftDict.setDictId(plate);
            dcNftDicts.add(dcNftDict);
        }
        boolean boo = dcNftDictMapper.insertBatch(dcNftDicts);
        if (!boo) insert = 0;
        return insert > 0;
    }

    /**
     * 发售藏品
     *
     * @param id 藏品标识
     * @return
     */
    @Override
    public Boolean saleDcNftInfo(String id) {
        //发售藏品
        DcNftInfo dcNftInfo = new DcNftInfo();
        dcNftInfo.setId(id);
        dcNftInfo.setStatus(NftInfoEnum.NFT_SALE_NUM.getValue());
        //修改藏品状态
        int i = dcNftMapper.updateById(dcNftInfo);
        //判断
        return i > 0;
    }

    /**
     * 发售藏品
     *
     * @param id 藏品标识
     * @return
     */
    @Override
    public Boolean saleDcNft(String id) {
        //根据id查看藏品详情信息
        DcNftInfo dcNftStatus = dcNftMapper.selectById(id);
        if (dcNftStatus.getStatus() != NftInfoEnum.NFT_BELOW.getValue()){
            return false;
        }
        //发售藏品
        DcNftInfo dcNftInfo = new DcNftInfo();
        dcNftInfo.setId(id);
        dcNftInfo.setStatus(NftInfoEnum.NFT_SALE.getValue());
        //修改藏品状态
        int i = dcNftMapper.updateById(dcNftInfo);
        //判断
        //redis当中放入集合 [key是nft: 藏品编号，value list(具体编号)
        //根据藏品id查询操作id
        return i > 0;
    }

    /**
     * 修改藏品信息
     *
     * @param dcNftInfoBo 藏品信息，包含藏品标识、藏品名称、藏品价格、藏品描述等属性
     * @return
     */
    @Override
    public Boolean updateDcNftInfo(DcNftInfoBo dcNftInfoBo) {
        //新建entti
        DcNftInfo dcNftInfo = BeanUtil.toBean(dcNftInfoBo, DcNftInfo.class);
        //获取创作者信息
        DcAuthorInfoVo authorDcInfoBo = dcNftInfoBo.getAuthorDcInfoBo();
        //获取创作者id标识
        dcNftInfo.setAuthorId(authorDcInfoBo.getId());
        //修改藏品信息
        int updateInt = dcNftMapper.updateById(dcNftInfo);
        //取出藏品id
        String id = dcNftInfo.getId();
        //删除藏品与字典中间表
        int intDict = dcNftDictMapper.deleteById(id);
        //取出字典信息
        List<String> plates = dcNftInfoBo.getPlates();
        List<DcNftDict> dcNftDicts = new ArrayList<>();
        for (String plate : plates) {
            DcNftDict dcNftDict = new DcNftDict();
            dcNftDict.setNftId(dcNftInfo.getId());
            dcNftDict.setDictId(plate);
            dcNftDicts.add(dcNftDict);
        }
        boolean boo = dcNftDictMapper.insertBatch(dcNftDicts);
        if (!boo) updateInt = 0;
        return updateInt > 0;
    }

    /**
     * 查看藏品详情信息
     *
     * @param id 藏品标识
     * @return
     */
    @Override
    public DcNftInfoVo getDcNftInfo(String id) {
        //根据id查看藏品详情信息
        DcNftInfoVo dcNftInfoVo = dcNftMapper.selectVoById(id);
        //查询创作者
        String authorId = dcNftInfoVo.getAuthorId();
        DcAuthorInfoVo authorDcInfoVo = dcAuthorInfoMapper.selectVoById(authorId);
        dcNftInfoVo.setAuthorDcInfoVo(authorDcInfoVo);
        //单词释义查询
        QueryWrapper<DcNftDict> parWrapper = new QueryWrapper<>();
        //单词表id查询释义表
        parWrapper.lambda().eq(DcNftDict::getNftId, id);
        //一个单词对应多个释义表
        List<DcNftDictVo> dcNftDicts = dcNftDictMapper.selectVoList(parWrapper);

        dcNftInfoVo.setNftDictVos(dcNftDicts);
        return dcNftInfoVo;
    }

    /**
     * 删除藏品信息
     *
     * @param id 藏品标识 根据藏品标识删除藏品信息
     * @return
     */
    @Override
    public Boolean delDcNftInfo(String id) {
        //创建藏品信息entity
        DcNftInfo dcNftInfo = new DcNftInfo();
        dcNftInfo.setId(id);
        dcNftInfo.setDeleteFlag(NftInfoEnum.NFT_DEL.getValue());
        int i = dcNftMapper.updateById(dcNftInfo);
        return i > 0;
    }

    /**
     * 下架藏品
     *
     * @param id 藏品标识 根据藏品标识下架藏品信息
     * @return
     */
    @Override
    public Boolean belowDcNftInfo(String id) {
        //下架藏品
        //创建藏品信息entity
        DcNftInfo dcNftInfo = new DcNftInfo();
        dcNftInfo.setId(id);
        dcNftInfo.setStatus(NftInfoEnum.NFT_BELOW.getValue());
        int i = dcNftMapper.updateById(dcNftInfo);
        return i > 0;
    }

    /**
     * 展示藏品
     *
     * @param id 藏品标识 根据藏品标识上架藏品信息
     * @return
     */
    @Override
    public Boolean showDcNftInfo(String id, Integer num) {
        //展示藏品ity
        DcNftInfo dcNftInfo = new DcNftInfo();
        dcNftInfo.setId(id);
        dcNftInfo.setNftShow(num);
        int i = dcNftMapper.updateById(dcNftInfo);
        return i > 0;
    }

    /**
     * 查询字典
     *
     * @param type
     * @return
     */
    @Override
    public List<NftDictVo> showDict(String type) {
        List<NftDictVo> nftDictVos = nftDictMapper.selectDict(type);
        return nftDictVos;
    }

    /**
     * 分页查询藏品
     *
     * @param type
     * @param keyword  藏品名称关键字
     * @param status   状态
     * @param pageNo   当前第几页
     * @param pageSize 每页显示多少条数据
     * @param show
     * @return
     */
    @Override
    public IPage<DcNftInfoVo> queryDcNftInfo(String type, String keyword, Integer status, Integer pageNo, Integer pageSize, Integer show) {
        //查询单词
        Page<DcNftInfo> dcNftInfoVoPage = new Page<>(pageNo, pageSize);
        QueryWrapper<DcNftInfo> nftInfoVoQueryWrapper = new QueryWrapper<>();
        nftInfoVoQueryWrapper.orderByDesc("create_time");
        LambdaQueryWrapper<DcNftInfo> lambda = nftInfoVoQueryWrapper.lambda();
        if (StringUtils.hasText(keyword)) lambda.like(DcNftInfo::getName, keyword);
        if (StringUtils.hasText(type)) lambda.like(DcNftInfo::getType, type);
        if (status != null) if (status != 0) lambda.eq(DcNftInfo::getStatus, status);
        lambda.eq(DcNftInfo::getDeleteFlag, 0);
        IPage<DcNftInfoVo> dcNftInfoVoIPage = dcNftMapper.selectVoPage(dcNftInfoVoPage, nftInfoVoQueryWrapper);
        //根据藏品id查询创作者
        List<DcNftInfoVo> records = dcNftInfoVoIPage.getRecords();
        for (DcNftInfoVo dcNftInfoVo : records) {
            //添加是否展示
            Integer nftShow = dcNftInfoVo.getNftShow();
            if (nftShow == 1) dcNftInfoVo.setShowNft(true);
            else dcNftInfoVo.setShowNft(false);
            String authorId = dcNftInfoVo.getAuthorId();
            //根据创作者id查询创作者
            DcAuthorInfoVo authorDcInfoVo = dcAuthorInfoMapper.selectVoById(authorId);
            dcNftInfoVo.setAuthorDcInfoVo(authorDcInfoVo);
        }
        dcNftInfoVoIPage.setRecords(records);
        return dcNftInfoVoIPage;
    }

    /**
     * 查询藏品发售时间
     *
     * @return
     */
    @Override
    public List<DcNftInfo> selectNftTime() {
        List<DcNftInfo> dcNftInfos = dcNftMapper.selectList();
        return dcNftInfos;
    }

    /**
     * 藏品上链
     *
     * @param id
     * @param contract
     * @return
     */
    @Override
    public Boolean updataNftContract(String id, String contract) {
        DcNftInfo dcNftInfo = new DcNftInfo();
        dcNftInfo.setId(id);
        dcNftInfo.setContract(contract);
        int i = dcNftMapper.updateById(dcNftInfo);
        return i > 1;
    }

}
